package com.briup.es.service.impl;

import com.briup.es.config.auth.SecurityUserContext;
import com.briup.es.config.constant.OrderStatus;
import com.briup.es.config.exception.ServiceException;
import com.briup.es.config.response.ResultCode;
import com.briup.es.domain.bean.Order;
import com.briup.es.domain.bean.Shopcar;
import com.briup.es.domain.dto.BookChangeNumDTO;
import com.briup.es.domain.dto.OrderCreateDTO;
import com.briup.es.domain.vo.OrderDetailVO;
import com.briup.es.domain.vo.OrderVO;
import com.briup.es.mapper.OrderMapper;
import com.briup.es.mapper.ShopCarMapper;
import com.briup.es.service.BookService;
import com.briup.es.service.OrderItemService;
import com.briup.es.service.OrderService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

@Service
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {

    private final OrderMapper orderMapper;
    private final ShopCarMapper shopCarMapper;
    private final OrderItemService orderItemService;
    private final BookService bookService;

    @Override
    public List<OrderVO> queryOrderList(Integer status) {
        // 查询当前用户下的所有订单
        Integer userId = SecurityUserContext.userId();
        return orderMapper.queryOrderListByUserId(userId, status);
    }

    @Override
    public OrderDetailVO queryOrderDetail(String orderId) {
        return orderMapper.queryByOrderId(orderId);
    }

    @Override
    // @Transactional Spring框架提供的声明式事务控制的注解，
    // 当某一个方法上标注了该注解，那么该方法就会被Spring框架管理事务
    @Transactional
    public void addOrder(OrderCreateDTO orderCreateDTO) {
        // 需要购物车项id 查询出该购物车中 对应的商品id以及对应的 商品数量
        List<Integer> shopCarIds = orderCreateDTO.getShopCarIds();
        List<Shopcar> shopCars = shopCarMapper.queryByIds(shopCarIds);
        if (CollectionUtils.isEmpty(shopCars) ||
                shopCars.size() != shopCarIds.size()) {
            // 如果根据购物车项id查询出的列表集合为空，那么说明该购物车项被删除了，无法生成订单
            // 或者查询出的购物车项 与 传入的购物车项id 数量不对等，也需要报错处理
            throw new ServiceException(ResultCode.SHOPCAR_ITEM_NUM_IS_ERROR);
        }

        // 调用BookService中的方法，校验图书是否下架 或 图书的库存是否足够，减少图书的库存
        List<BookChangeNumDTO> dtoList = shopCars.stream().map(shopcar -> BookChangeNumDTO.builder()
                        .bookId(shopcar.getBookId()).changeNum(-shopcar.getNum()).build())
                .toList();
        // 调用BookService中的方法，用于修改图书商品的库存
        bookService.changeStoreNum(dtoList);

        // 创建订单对象，添加该数据到订单表中
        Order order = initOrder(orderCreateDTO);
        orderMapper.addOrder(order);

        // 添加订单项的数据
        orderItemService.addOrderItems(order.getId(), shopCars);

        // 生成订单后，需要将购物项中的对应数据进行删除
        shopCarMapper.batchDelete(shopCarIds);
    }

    @Override
    @Transactional
    public void cancelOrder(String orderId) {
        // 关闭订单，即修改订单状态
        OrderDetailVO detailVO = orderStatusTranslate(orderId, OrderStatus.NOT_PAY,
                OrderStatus.CLOSED, ResultCode.ORDER_CAN_NOT_CLOSE);

        // 如果订单可以关闭，那么关闭订单，并且将该订单对应的商品库存修复
        List<BookChangeNumDTO> dtoList = detailVO.getOrderItems().stream().map(orderItemVO -> BookChangeNumDTO
                .builder().bookId(orderItemVO.getBookId())
                .changeNum(orderItemVO.getNum()).build()).toList();

        // 修改图书库存数量
        bookService.changeStoreNum(dtoList);
    }

    @Override
    public void completeOrder(String orderId) {
        // 确认收货，修改订单状态
        orderStatusTranslate(orderId,OrderStatus.SENT,
                OrderStatus.RECEIVED,ResultCode.ORDER_CAN_NOT_COMPLETE);
    }

    private OrderDetailVO orderStatusTranslate(String orderId, OrderStatus preStatus,
                                               OrderStatus newStatus, ResultCode errorCode){
        // 确保该订单存在
        OrderDetailVO detailVO = orderMapper.queryByOrderId(orderId);
        if (detailVO == null){
            throw new ServiceException(ResultCode.ORDER_IS_NOT_EXISTS);
        }

        // 如果订单存在，确保该订单当前状态 与待修改状态的 前置状态 一致
        if (!Objects.equals(detailVO.getStatus(), preStatus.getCode())){
            throw new ServiceException(errorCode);
        }

        // 修改订单状态
        orderMapper.changeStatus(orderId,newStatus.getCode());

        return detailVO;
    }


    private Order initOrder(OrderCreateDTO orderCreateDTO) {
        return Order.builder()
                // 订单id通过UUID和 briup 组合生成
                .id("briup" + UUID.randomUUID().toString()
                        .replace("-", ""))
                .userId(SecurityUserContext.userId())
                .status(OrderStatus.NOT_PAY.getCode())
                .createDate(LocalDateTime.now())
                .receiveUsername(orderCreateDTO.getReceiveUsername())
                .receiveAddress(orderCreateDTO.getReceiveAddress())
                .receivePhone(orderCreateDTO.getReceivePhone())
                .build();
    }
}
